package decomposition;

import matrix_operations.Matrix;

public abstract class DecompositionLDLT {

	private static String msg = ""; 
			
	public static Matrix[] factorizing(Matrix A) {
		
		msg = "";

		if (A.getN() != A.getM()) {
			msg = "Erro! The matrix can not be facored, because is not a square matrix.";
			System.out.println(msg);
			return null;
		}

		int n = A.getN();

		double sum = 0;

		Matrix L = Matrix.getIdentityMatrix(n);
		Matrix D = Matrix.getIdentityMatrix(n);

		for (int i = 0; i < n; i++) {

			sum = 0;
			for (int j = 0; j < i; j++)
				sum += Math.pow(L.getValue(i, j), 2) * D.getValue(j, j);
			
			if ((A.getValue(i, i) - sum) <= 0){
				msg = "Erro! The matrix can not be facored, because is not a positve definite."; 
				System.out.println(msg);
				return null;				
			}


			D.setValue(i, i, A.getValue(i, i) - sum);

			for (int j = i + 1; j < n; j++) {

				sum = 0;
				for (int k = 0; k < i; k++)
					sum +=
							L.getValue(j, k) * L.getValue(i, k)
									* D.getValue(k, k);
				if (D.getValue(i, i) == 0) {
					
					msg = "Erro! The Matrix cannot be factored with LDLT method";
					System.out.println(msg);
					return null;
				}
				L.setValue(j, i, (A.getValue(j, i) - sum) / D.getValue(i, i));
			}

		}

		return (new Matrix[] { L, D });
	}

	public static Matrix solveSysem(Matrix[] LDLT, Matrix B) {
		
		if (LDLT == null){
			msg = "Erro! The Matrix cannot be factored with LDLT method";
			return null;
		}		

		
		Matrix y = new Matrix(B.getN(), 1);
		Matrix z = new Matrix(B.getN(), 1);
		Matrix x = new Matrix(B.getN(), 1);
		double sum;
		int n = B.getN();
		
		msg = "";

		//y_0 = b_0
		y.setValue(0, 0, B.getValue(0, 0));

		//Ly = b
		for (int i = 1; i < n; i++) {
					
			sum = 0;
			for (int j = 0; j < i; j++) {
				sum += LDLT[0].getValue(i, j) * y.getValue(j, 0);
			}
			
			y.setValue(i, 0, B.getValue(i, 0) - sum);
		}
		
		// Dz = y
		for (int i = 0; i < n; i++) {
			z.setValue(i, 0, y.getValue(i, 0) / LDLT[1].getValue(i, i));
		}
		
		//x_n = z_n
		x.setValue(n-1, 0, z.getValue(n-1, 0));

		// LTx = z
		for (int i = n - 2; i >= 0; i--) {
			sum = 0;
			for (int j = i + 1; j < B.getN(); j++)
				sum += LDLT[0].getValue(j, i) * x.getValue(j, 0);
			x.setValue(i, 0, z.getValue(i, 0) - sum);
		}

		return x;
	}
	
	public static String getMsg(){
		return msg;
	}
}